#include "ASMInstruction.hpp"
#include "CodeGen.hpp"
#include "Module.hpp"

#include <iostream>
#include <memory>
#include <unordered_map>

// 主函数声明：将高级语言翻译为目标架构汇编
void translate_main(CodeGen *codegen);

int main() {
    // 初始化编译器模块和代码生成器
    auto *module = new Module();
    auto *codegen = new CodeGen(module);

    // 指定后续生成的汇编代码属于.text段（代码段）
    codegen->append_inst(".text", ASMInstruction::Atrribute);

    // 执行实际的代码翻译工作
    translate_main(codegen);

    // 输出生成的汇编代码
    std::cout << codegen->print();
    
    // 清理资源
    delete codegen;
    delete module;
    return 0;
}

// RISC-V浮点运算和类型转换实现
void translate_main(CodeGen *codegen) {
    // 符号表：记录变量在栈帧中的偏移位置
    std::unordered_map<std::string, int> offset_map;

    /* ============== 函数声明部分 ============== */
    codegen->append_inst(".globl main", ASMInstruction::Atrribute);  // 全局可见符号
    codegen->append_inst(".type main, @function", ASMInstruction::Atrribute); // 函数类型标识

    /* ============== 函数入口点 ============== */
    codegen->append_inst("main", ASMInstruction::Label);  // 函数入口标签

    /* ============== 序言部分 (Prologue) ============== */
    // 分配32字节栈空间（包含保存寄存器和局部变量的空间）
    codegen->append_inst("addi sp, sp, -32");
    // 保存返回地址寄存器(ra)到栈中
    codegen->append_inst("sd ra, 24(sp)");
    // 保存旧的帧指针(s0)
    codegen->append_inst("sd s0, 16(sp)");
    // 设置新的帧指针(s0 = sp + 32)
    codegen->append_inst("addi s0, sp, 32");

    /* ============== 代码主体部分 ============== */
    codegen->append_inst(".main_label_entry", ASMInstruction::Label);  // 主代码段标签

    /* 浮点指针分配 */
    offset_map["%op0"] = -24;  // 指针变量存储在s0-24位置
    offset_map["float_val"] = -28; // 实际浮点值存储在s0-28位置
    codegen->append_inst("addi t0, s0, -28"); // 计算浮点变量地址
    codegen->append_inst("sd t0, -24(s0)");   // 存储指针到%op0

    /* 浮点常量存储（3.14） */
    codegen->append_inst("li t0, 0x4048f5c3"); // 3.14的单精度IEEE 754表示
    codegen->append_inst("fmv.w.x ft0, t0");   // 将位模式移动到浮点寄存器ft0
    codegen->append_inst("ld t1, -24(s0)");    // 获取%op0指向的地址
    codegen->append_inst("fsw ft0, 0(t1)");    // 存储浮点值到内存

    /* 浮点值加载 */
    offset_map["%op1"] = -32;  // 加载的浮点值存储在s0-32位置
    codegen->append_inst("ld t0, -24(s0)");    // 再次获取%op0指向的地址
    codegen->append_inst("flw ft0, 0(t0)");    // 从内存加载浮点值到ft0
    codegen->append_inst("fmv.x.w t1, ft0");   // 将浮点值移动到整数寄存器t1
    codegen->append_inst("sw t1, -32(s0)");    // 存储浮点位模式

    /* 浮点到整数的类型转换 */
    offset_map["%op2"] = -36;  // 转换结果存储在s0-36位置
    codegen->append_inst("lw t0, -32(s0)");    // 加载浮点位模式
    codegen->append_inst("fmv.w.x ft0, t0");   // 移动到浮点寄存器
    // 执行浮点到整数的转换（向零舍入模式）
    codegen->append_inst("fcvt.w.s t1, ft0, rtz"); 
    codegen->append_inst("sw t1, -36(s0)");    // 存储转换后的整数值

    /* 函数返回部分 */
    codegen->append_inst("lw a0, -36(s0)");    // 加载返回值到a0寄存器
    codegen->append_inst("j .main_exit");      // 跳转到公共退出点

    /* ============== 收尾部分 (Epilogue) ============== */
    codegen->append_inst(".main_exit", ASMInstruction::Label);
    // 恢复返回地址寄存器(ra)
    codegen->append_inst("ld ra, 24(sp)");
    // 恢复旧的帧指针(s0)
    codegen->append_inst("ld s0, 16(sp)");
    // 释放栈空间（32字节）
    codegen->append_inst("addi sp, sp, 32");
    // 函数返回（跳转到ra寄存器指定的地址）
    codegen->append_inst("jr ra");
}
